﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibMinecraft.Server;
using System.Reflection;
using LibMinecraft.Model.Packets;
using LibMinecraft.Model;

namespace PartyCraftServer.Commands
{
    /// <summary>
    /// All server commands
    /// </summary>
    public abstract class Command
    {
        public static bool CommandsEnabled = true;
        public static string ReasonForDisabled = "";

        public static void Execute(RemoteClient client, string command)
        {
            if (!PartyCraft.IsOp(client) && !CommandsEnabled)
            {
                client.PacketQueue.Enqueue(new ChatMessagePacket(ChatColor.Red + ReasonForDisabled));
                return;
            }
            if (!CommandsEnabled)
                client.SendChat(ChatColor.Gold + "WARNING: Commands are currently disabled for non-OPs.");
            if (string.IsNullOrWhiteSpace(command))
                return; // TODO: Error?
            command = command.Substring(1);

            string[] commandParts = command.Split(' ');
            foreach (var t in AppDomain.CurrentDomain.GetAssemblies()
                .Concat(PartyCraft.PluginManager.InstalledAssemblies)
                .SelectMany(s => s.GetTypes())
                .Where(p => typeof(Command).IsAssignableFrom(p) && p != typeof(Command)))
            {
                Command c = (Command)Activator.CreateInstance(t);
                string[] aliases = new string[0];
                if (PartyCraft.Settings.ContainsKey("command.alias." + c.DefaultCommand))
                    aliases = PartyCraft.Settings["command.alias." + c.DefaultCommand].Replace(" ", "").Split(',');
                if (c.DefaultCommand.ToLower() == commandParts[0].ToLower() ||
                    aliases.Contains(commandParts[0].ToLower()))
                {
                    if (c.RequiresOp)
                    {
                        if (!PartyCraft.IsOp(client))
                        {
                            client.SendChat(ChatColor.Red + "You don't have permission to use that command.");
                            return;
                        }
                    }
                    string[] parameters = command.Substring(command.IndexOf(' ') + 1).Split(' ');
                    if (command.IndexOf(" ") == -1)
                        parameters = new string[0];
                    c.ExecuteCommand(client, parameters);
                    return;
                }
            }
            client.SendChat(ChatColor.Red + "The specified command was not found.");
        }

        public abstract bool RequiresOp { get; }

        /// <summary>
        /// The default string used to access this command.
        /// For example, /stop's DefaultCommand is "stop"
        /// </summary>
        public abstract string DefaultCommand { get; }

        /// <summary>
        /// Text output when /help is used.
        /// </summary>
        public abstract string Documentation { get; }

        /// <summary>
        /// This will be called for your command when a user
        /// or the console calls it.  If the console uses it,
        /// client will be null.
        /// </summary>
        public abstract void ExecuteCommand(RemoteClient client, params string[] parameters);
    }

    [Flags]
    public enum CommandType
    {
        Player,
        Console,
        Remote,
    }
}
